/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ACH.app.util;

import ACH.app.util.ReadingDataDB.ObjData;
import ACH.app.util.WordRF;
import ACH.app.util.General;
import ACH.app.util.Synonym;
import ACH.app.util.Antonym;
import ACH.mod.Snippet.DistanceCalculator;
import ACH.mod.Snippet.Search;
import ACH.app.util.AntonymLexPattern;
import ACH.object.SearchEngine;
import ACH.object.ResultOfMetrics;
import cenidet.object.api.LinguisticPhenomAPI;
import com.opensymphony.xwork2.ActionSupport;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;


//import ACH.mod.Snippet.DistanceCalculator;
/**
 *
 * @author adriancruz11c
 */
public class Inicio extends ActionSupport {   
    private final ObjData data;    
    private SearchEngine se;
    private final Connection conn;
    private String summary[];
    private int numResultsFromW;
    private String query1;    
    LinguisticPhenomAPI myAPI;
    private double resultSyn,synNGD,cooc, finalMetric, paraphrase;
    private double  pwnet,pngd,pcooc,pmatch,pwrf,finalResultt;
    
    private double mAntWeb, mHypWeb;
    
    private double rw_l,rw_r;        
    private String infoHTML;    
    private Map< String, String[] > vocSynsetsWNet;
    private Map< String, JSONObject > vocJsonSE;
    private Map< String, JSONObject > vocJsonSEpar;
    private double resulySynWRF;
    List<ResultOfMetrics> objRm = new ArrayList<ResultOfMetrics>();
    private ResultOfMetrics[] resultOfRM;
    private Map<String, JSONObject> AntJsonSEparSize;
    private Map<String, JSONObject> HypJsonSEparSize;
   
    
    //public Inicio() throws ClassNotFoundException, SQLException {
    public Inicio() throws ClassNotFoundException, SQLException{        
        ServletContext sc = ServletActionContext.getServletContext();
        ReadingDataDB datacf = new ReadingDataDB();
        this.data = datacf.getObjData();             
        System.out.println("jdbc:mysql://" + data.getBdHost() + "/" + data.getBdNombre() + "?user=" + data.getBdUsuario() + "&password=" + data.getBdPassword());        
        Class.forName("com.mysql.jdbc.Driver");
        conn = DriverManager.getConnection("jdbc:mysql://" + data.getBdHost() + "/" + data.getBdNombre() + "?user=" + data.getBdUsuario() + "&password=" + data.getBdPassword());
        myAPI  = new LinguisticPhenomAPI(data.getBdHost(), data.getBdEuroWN(), data.getBdWordNet(), data.getBdUsuario(), data.getBdPassword(), data.getBdPort());
    }
    /*
    @Override
    public String execute() throws Exception {
        throw new UnsupportedOperationException("Not supported yet.");
               
    }*/
    public String dataSearchE() throws IOException, JSONException{
        /*
        Search sp = new Search();
        this.setSummary(sp.mainPrint("CENIDET", 1));
                
        se = new SearchEngine();
        se.setKey(data.getSEGoogleKey());        
        se.setClientID(data.getSEGoogleClientID());       
        se.setMaximusQuerys(data.getSEGoogleMaximusQuerys());       
        System.out.println("sinError");
        this.setNumResultsFromW(sp.numResultsFromWeb("CENIDET"));
        System.out.println("sinError:confirmado");
        *****Eliminar*/
        return SUCCESS;
        
    }
    public void coreOperations(String [][]ul) throws SQLException, IOException, JSONException{                       
        // falta llenar los arreglos para antonimos **********
        vocSynsetsWNet = new HashMap< String, String[] >();
        vocJsonSE = new HashMap< String, JSONObject >();
        vocJsonSEpar = new HashMap< String, JSONObject >();    
        
        AntJsonSEparSize = new HashMap< String, JSONObject >();  
        HypJsonSEparSize = new HashMap< String, JSONObject >();  
        
        String []snipUL1; String []snipUL2;
        String strictTM0="",strictTM1="";
        JSONObject jpar=null;/*
        System.out.println(":::");
        for(String[] tm : ul){ 
         for (String arr: tm)
             System.out.println(arr);
        }                */
        String []mtz=new String[ul.length];        
        for(String[] tm : ul){ //get JSON  for each unity lexical
          if (tm[0]!=null && tm[1]!=null) {  
          strictTM0="\""+tm[0]+"\""; // if UL = "U L" | "UL"
          strictTM1="\""+tm[1]+"\""; // if UL = "U L" | "UL"   
          if(! (vocJsonSE==null || vocSynsetsWNet==null)) {                                 
           if (!vocJsonSE.containsKey(tm[0])){               
                   vocJsonSE.put(tm[0], Search.readJsonFromQ("", tm[0], 1, this.data));                   
                   vocSynsetsWNet.put(tm[0], ((String)myAPI.getSynsetsAPI(tm[0], "English")).split(":")); 
                   
           }
           if (!vocJsonSE.containsKey(tm[1])){
                   vocJsonSE.put(tm[1], Search.readJsonFromQ("", tm[1], 1,this.data));
                   vocSynsetsWNet.put(tm[1], ((String)myAPI.getSynsetsAPI(tm[1], "English")).split(":"));
                           //((String)myAPI.getSynsetsAPI(tm[1], "English")).split(":"));
           }
                     
           jpar=Search.readJsonFromQ(strictTM1, tm[0], 1,this.data); vocJsonSEpar.put(tm[0]+"y"+tm[1],jpar);
           jpar=Search.readJsonFromQ(strictTM0, tm[1], 1,this.data); vocJsonSEpar.put(tm[1]+"y"+tm[0],jpar);
           jpar=Antonym.getJSONPatternWeb(tm[0], tm[1], this.data);  AntJsonSEparSize.put(tm[1]+"y"+tm[0], jpar);
                                                                     AntJsonSEparSize.put(tm[0]+"y"+tm[1], jpar);
           jpar=Hyponym.getJSONPatternWeb(tm[0], tm[1], this.data);  HypJsonSEparSize.put(tm[1]+"y"+tm[0], jpar);
                                                                     HypJsonSEparSize.put(tm[0]+"y"+tm[1], jpar);                                                                     
          }else{ //System.out.println("98 OK t1"+tm[0]+" t2:"+tm[1]);
                 vocSynsetsWNet.put(tm[0], ((String)myAPI.getSynsetsAPI(tm[0], "English")).split(":"));                                                                       
                 vocSynsetsWNet.put(tm[1], ((String)myAPI.getSynsetsAPI(tm[1], "English")).split(":"));
                 vocJsonSE.put(tm[0], Search.readJsonFromQ("", tm[0], 1,this.data));
                 vocJsonSE.put(tm[1], Search.readJsonFromQ("", tm[1], 1,this.data));
                 snipUL1=Search.mainPrint(tm[0], 2,this.data,vocJsonSE.get(tm[0]));
                 snipUL2=Search.mainPrint(tm[1], 2,this.data,vocJsonSE.get(tm[1]));
          }
                    
           metrics(tm[0],tm[1], tm[2],vocJsonSE,vocJsonSEpar,vocSynsetsWNet, AntJsonSEparSize, HypJsonSEparSize);               
         } else { System.out.println("N/A");}
        }
    }
    public void metrics(String qt1, String qt2, String marked, Map< String, JSONObject > jsonSE,Map< String, JSONObject > jsonSEpar, Map< String, String[] > SynWN, Map< String, JSONObject > AntWeb, Map< String, JSONObject > HypWeb) throws UnsupportedEncodingException, IOException, JSONException, SQLException{
        boolean []considerMetric=new boolean[5]; //0 synOfWNet; 1 NGD, 2 Cooc, 3 parafrasis, 4 Wordreference
        General gn=new General();
        for(int i=0;i<considerMetric.length;i++) considerMetric[i]=true;
        String []arr1=SynWN.get(qt1);
        String []arr2=SynWN.get(qt2); 
        String []ulx=new String[2];
        if(qt1.compareTo(qt2)<0){ulx[0]=qt1; ulx[1]=qt2;}else{ulx[1]=qt1; ulx[0]=qt2;}
                
        if (arr1.length>1 && arr2.length>1) resultSyn = gn.matchArrays(arr1, arr2);//gn.rSynonym(arr1, arr2);//Syn of WordNet
          else considerMetric[0]=false;        
        Double ngd = DistanceCalculator.getNGD(jsonSE.get(qt1), jsonSE.get(qt2), jsonSEpar.get(ulx[0]+"y"+ulx[1]));
        synNGD=1-ngd; if(synNGD<0.0)considerMetric[1]=false;        
        cooc=DistanceCalculator.getCooc(jsonSE.get(qt1), jsonSE.get(qt2), jsonSEpar.get(qt1+"y"+qt2),jsonSEpar.get(qt2+"y"+qt1));
        if (cooc<((Math.sin(0)+(0.3/2.0))/2.0)) 
            considerMetric[2]=false;                     
        double []matchW=this.matchWeb(Search.mainPrint(qt1, 1,this.data,jsonSE.get(qt1)), qt1, Search.mainPrint(qt2, 1,this.data,jsonSE.get(qt2)), qt2);
        rw_l=matchW[0];
        rw_r=matchW[1];
        if(matchW.length==2)
            paraphrase=(matchW[0]+matchW[1])/2.0;
            else {paraphrase=0.0; considerMetric[3]=false;}
        System.out.println("------------1");
        String [][]WRF=WordRF.getWordReference(data.getApiWordRfURL()+data.getApiWordRfKEY()+data.getApiWordRfURI(),qt1, qt2);        
        System.out.println("------------2");   
        resulySynWRF=0.0;
        int xx=0;
        String sensesLogS="";
        for (String []x: WRF){
            System.out.println("\n"+(xx++));
            for (String y: x){
                System.out.println(y);
                sensesLogS=y;
            }
        }
        /////////
        if (WRF.length==3){
            System.out.println("------------3");
            if (WRF[2]!=null)
            if (WRF[2].length==3){
                for (String x: WRF[2])
                    System.out.println(x);
                System.out.println("------------3.1");
                /*int wrf1=Integer.getInteger(WRF[2][0]);
                int wrf2=Integer.getInteger(WRF[2][1]);  */
                double sensesLog=Double.parseDouble(sensesLogS);
                System.out.println("------------4");
                if (WRF[0]!=null && WRF[1]!=null && sensesLog>=0.0){
                    System.out.println("------------5");
                    resulySynWRF=gn.matchArrays(WRF[0], WRF[1]); //gn.rSynonym(WRF[0], WRF[1]);
                    if (resulySynWRF > 0.0)
                        resulySynWRF=(resulySynWRF+sensesLog)/2.0;                                   
                        
                }else considerMetric[4]=false;
            }else considerMetric[4]=false;
        }else considerMetric[4]=false;
        
        mAntWeb=Antonym.sizeAntWeb(AntWeb.get(ulx[0]+"y"+ulx[1]));  // [0-1],    
        mHypWeb=Hyponym.sizeHypWeb(HypWeb.get(ulx[0]+"y"+ulx[1])); //Checar
        this.finalMetric=fullMetric(qt1, qt2, marked, resultSyn, synNGD, cooc, paraphrase, resulySynWRF, mAntWeb,mHypWeb, considerMetric);
       
    }
  
    public double fullMetric(String qt1, String qt2, String marked,double Wnet, double ngd, double cooc, double match, double wrf, double antWeb, double hypWeb, boolean []tf) throws SQLException{
        double tot=0.0, thresholdP=0.48;        // checar bien lo de las ponderaciones
        
        //uble match=(matchW[0]+matchW[1])/2.0;
 Wnet=Wnet*pwnet;
    ngd=ngd*pngd;
         cooc=cooc*pcooc;
                 match=match*pmatch;
                 wrf=wrf*pwrf;
        if (tf[0]){ tot=tot+Wnet;} 
           else{tot=tot+(pwnet*thresholdP);}// 0.8 penalizar
        if (tf[1]) {tot=tot+ngd;}   
           else{tot=tot+(pngd*thresholdP);}
        if (tf[2]) {tot=tot+cooc;} 
           else{tot=tot+(pcooc*thresholdP);}
        if (tf[3]) {tot=tot+match;} 
           else{tot=tot+(pmatch*thresholdP);}        
        if (tf[3]) {tot=tot+wrf;} 
           else{tot=tot+(pwrf*thresholdP);}          
        System.out.println("\tSumatot="+tot);        
        System.out.println("\tWnet="+Wnet+"\tngd="+ngd+"\tcooc="+cooc+"\ttot="+tot);        
        //Checar orden de argumentos
        //if (marked.equalsIgnoreCase("s"))
        // Synonym.isSynonymOfWordNet(qt1, qt2, myAPI)  ::: checar en wordnet y wordreference
        //isAntonymOfWordNet(qt1, qt2, myAPI) ::: NO ES posible checar en wordreference (no hay antonyms)
        boolean hyponymWeb=false;
        if (hypWeb>0.2)
            hyponymWeb=true;
            
        ResultOfMetrics rm = new ResultOfMetrics(Wnet,ngd,cooc,match,wrf,
                tot,tf, 
                Synonym.isSynonymOfWordNet(qt1, qt2, myAPI), hyponymWeb, 
                antWeb, Antonym.isAntonymOfWordNet(qt1, qt2, myAPI), AntonymLexPattern.isAntonym(qt1, qt2),
                qt1, qt2,marked);
        
        this.objRm.add(rm);
        this.finalResultt=tot;
        return tot;
    }
    public String QueryForm() throws SQLException, IOException, JSONException{
        boolean []considerMetric=new boolean[3]; //0 synOfWNet; 
        HttpServletRequest request = ServletActionContext.getRequest();
        /*String qt1 = request.getParameter("queryT1");
        String qt2 = request.getParameter("queryT2");*/
        String qtx = request.getParameter("query");
        String []ULs=qtx.split("\n");
        String []ul;
        String [][]lexical;
        lexical=new String[ULs.length][3];
        for (int i=0;i<ULs.length; i++){
            ul=ULs[i].split("@");            
            if (ul.length==2){                
                lexical[i][0]=ul[0]; 
                lexical[i][1]=ul[1]; //ul[2] debe vales 's'                
                lexical[i][2]="s"; //ul[2] debe vales 's'                
            }else if (ul.length>=3){                
                lexical[i][0]=ul[0]; 
                lexical[i][1]=ul[1]; //ul[2] debe vales 's'                
                lexical[i][2]=ul[2]; //ul[2] debe vales 's'                
            }else{ 
                lexical[i][0]=null;
                lexical[i][1]=null;
                lexical[i][2]="¿";
            }
            //query1="Syn("+ul[0]+","+ul[1]+")";
        }
        
        
               pwnet=17.0/100.0;
                pngd=27.0/100.0;
               pcooc=21.0/100.0;          
              pmatch=16.0/100.0;
                pwrf=19.0/100.0;
                
        this.coreOperations(lexical);
        
        /*
       int i;
        if ((i = objRm.size()) > 0) {
            resultOfRM = new ResultOfMetrics[i];
            i = 0;
            for (ResultOfMetrics p : objRm) {
                resultOfRM[i++] = p;
            }
            System.out.println("Tabla elems:"+i);
        }
        //impriir resultOfRM en forma de tabla en el formulario
        */
        return SUCCESS;
    }
    //public int []matchWeb(String []mw1, String t1, String []mw2, String t2, Search Snp) throws UnsupportedEncodingException, IOException, JSONException{
        public double matchX(String []mw1, String t1, String t2) throws UnsupportedEncodingException, IOException, JSONException{
        System.out.println("\n\n\n\n*************CHECK: **********\n");        
        String []arrS;
        String cadSearch="";
        int acumule=0,total=0, cont=0;        
        String tmp="";
        long numResult=0;
        double log10=0.0;
        Search se=new Search();
        String cadQ="";
        for(int i=0; i<mw1.length; i++){
            System.out.println();
           if (!(mw1[i]==null || mw1[i].isEmpty())){
           tmp=mw1[i].replace("...", "");
           arrS=tmp.split(" ");                    
           for(int j=0; j<arrS.length-3; j++){    
               //System.out.println("#" + j+1);
               if(arrS[j].equals(t1)){ 
                   System.out.println(t1+" in "+tmp+ "=OK");
                   if (j>2)
                   cadSearch=arrS[j-3]+" "+arrS[j-2]+" "+arrS[j-1]+" "+t2+" "+arrS[j+1]+" "+arrS[j+2]+" "+arrS[j+3];                   
                   else if(j>1)
                       cadSearch=arrS[j-2]+" "+arrS[j-1]+" "+t2+" "+arrS[j+1]+" "+arrS[j+2]+" "+arrS[j+3];                   
                   else if (j>0)
                       cadSearch=arrS[j-1]+" "+t2+" "+arrS[j+1]+" "+arrS[j+2]+" "+arrS[j+3];                                      
                   cadQ=cadQ +"\"" +cadSearch + "\" OR ";
                   cont++;                                      
                   break;
                }               
           }
           }
        }
        if(cadQ.length()>4)
        cadQ=cadQ.substring(0, cadQ.length()-4);//quitar el ultimo ' OR '        
        long r=se.numResultsFromWeb(cadQ,this.data);        
        if (r>0.0)
            log10 = Math.log10(0.0+r)* Math.E /10;//CHEKKKKKKKKKKK por que al final da infinity        
        //total=se.numResultsFromWeb(cadQ,this.data);        
        System.out.println(log10);
        
        return log10;
        }
    public double []matchWeb(String []mw1, String t1, String []mw2, String t2) throws UnsupportedEncodingException, IOException, JSONException{
        System.out.println("\n\n\n\n*************CHECK: **********\n");                                
        double []rW=new double[2];
        rW[0]=this.matchX(mw1, t1, t2);
        rW[1]=this.matchX(mw2, t2, t1); 
        if(rW[0]>1.0) rW[0]=1.0;
        if(rW[1]>1.0) rW[1]=1.0;
        System.out.println("\n");
        return rW;
    }


    public List<ResultOfMetrics> getObjRm() {
        return objRm;
    }

    public double getResulySynWRF() {
        return resulySynWRF;
    }
    


    public double getParaphrase() {
        return paraphrase;
    }
    
    public SearchEngine getSe() {
        return se;
    }

    public String[] getSummary() {
        return summary;
    }

    public void setSummary(String[] summary) {
        this.summary = summary;
    }

    public int getNumResultsFromW() {
        return numResultsFromW;
        
    }

    public void setNumResultsFromW(int numResultsFromW) {
        this.numResultsFromW = numResultsFromW;
    }

    public String getQuery1() {
        return query1;
    }

    public double getResultSyn() {
        return resultSyn;
    }

    public double getSynNGD() {
        return synNGD;
    }

    public double getRw_l() {
        return rw_l;
    }

    public double getRw_r() {
        return rw_r;
    }
    public double getCooc(){
    return cooc;
    }

    public double getFinalMetric() {
        return finalMetric;
    }

    public String getInfoHTML() {
        return infoHTML;
    }

    public double getPwnet() {
        return pwnet;
    }

    public double getPcooc() {
        return pcooc;
    }

    public double getPmatch() {
        return pmatch;
    }

    public double getPngd() {
        return pngd;
    }

    public double getPwrf() {
        return pwrf;
    }
    
    
}
